﻿using System.Linq;

using Buddy.BehaviorTree;
using Buddy.CommonBot;
using Buddy.CommonBot.Logic;
using Buddy.Swtor;
using Buddy.Swtor.Objects;

using WingIt;
using WingIt.Dynamics;
using WingIt.Routines.Mirrors;

namespace WingIt.Routines
{
    [RevisionControlId("$Id: Concealment_Scrapper.cs 696 2012-08-13 17:20:41Z Chinajade $")]
    public class OperativeConcealment_ScoundrelScrapper : MirrorRoutine
    {
        // MAINTAINERS NOTES:
        // * You will notice that lambda expression argument names are unique (e.g., "darkWardOn", "darkWardWhen", "joltWhen"),
        //   instead of generic (e.g., "ctx", "ret", "on", "doWhen", "castWhen").  PLEASE honor this convention!
        //   This allows us to quickly localize problems when looking at user's logs.  When the BehaviorTree encounters an exception
        //   (e.g., "object not found"), the location where an exception is thrown is identifiable only through the name
        //   of the lambda expression argument.  Such is the nature of BehaviorTrees.

        [Behavior(BehaviorType.Pull)]
        [Class(CharacterClass.Agent, AdvancedClass.Operative, SkillTreeId.OperativeConcealment)]
        [Class(CharacterClass.Smuggler, AdvancedClass.Scoundrel, SkillTreeId.ScoundrelScrapper)]
        public static Composite OperativeConcealment_ScoundrelScrapper_Pull()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                CreateBTPS.BWcoreFixup_WaitForHarvestComplete(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                BuffSelf("Stealth"),
                CreateBTPS.MoveWithinRangeAndLoS(target => MyTarget, Global.Distance.Melee),
                //Movement.MoveBehind(MyTarget, Global.Distance.Melee),
                new Decorator(whenCrowdControlNeeded => CCTarget != null,
                    Cast("Slice Droid", sliceDroidOn => CCTarget, sliceDroidWhen => TargetSelect.ViableTargetList().FirstOrDefault(t => t.HasMirrorDebuffStacks("Slice Droid")) == null)),
                BuffSelf("Acid Blade"), // Flechette Round
                Cast("Hidden Strike", hiddenStrikeWhen => Me.HasBuff("Stealth")), // Shoot First
                Cast("Backstab"), // Back Blast
                Cast("Shiv") // Blaster Whip
            );
        }

        [Behavior(BehaviorType.Combat)]
        [Class(CharacterClass.Agent, AdvancedClass.Operative, SkillTreeId.OperativeConcealment)]
        [Class(CharacterClass.Smuggler, AdvancedClass.Scoundrel, SkillTreeId.ScoundrelScrapper)]
        public static Composite OperativeConcealment_ScoundrelScrapper_Combat()
        {
            return new PrioritySelector(
                LazyRaider.CreateBTPS_NotifyAndShortCircuitWhenCombatDisabled(),
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),

                CreateBTPS.StopWithinRangeAndLoS(target => MyTarget, Global.Distance.Melee),

                // General
                Cast("Escape", escapeWhen => Global.CCBreak), // Escape
                Cast("Evasion", evasionWhen => Me.HealthPercent <= Global.Health.OhShit), // Dodge
                Cast("Cloaking Screen", cloakingScreenWhen => Me.HealthPercent <= Global.Health.OhShit && Me.CanMirrorCast("Evasion", Me)), // Disappearing Act
                Cast("Stim Boost", stimBoostWhen => Me.HasMirrorBuffStacks("Tactical Advantage")), // Pugnacity
                Cast("Adrenaline Probe", adrenalineProbeWhen => Resource <= 30), // Cool Head

                // CC
                new Decorator(whenCrowdControlNeeded => CCTarget != null,
                    Cast("Slice Droid", sliceDroidOn => CCTarget, sliceDroidWhen => TargetSelect.ViableTargetList().FirstOrDefault(t => t.HasMirrorDebuffStacks("Slice Droid")) == null)),
                Cast("Surrender", surrenderWhen => Me.IsInParty()),
                Cast("Shield Probe", shieldProbeWhen => Me.HealthPercent <= Global.Health.High), // Defense Screen
                Cast("Flash Bang", flashBangWhen => MyTarget.MobCountAround(Global.Distance.MeleeAoE) >= 4),
                Cast("Debilitate", debilitateWhen => Global.RequiresCrowdControl), // Dirty Kick

                // Healing
                new Decorator(healWhen => (HealTarget != null) && (HealTarget.HealthPercent <= Global.Health.Mid),
                    new PrioritySelector
                    (
                        Cast("Kolto Infusion", koltoInfusionOn => HealTarget, koltoInfusionWhen => Me.HasMirrorBuffStacks("Tactical Advantage", 1)),
                        Cast("Diagnostic Scan", diagnosticScanOn => HealTarget, diagnosticScanWhen => Resource <= 30),
                        Cast("Kolto Injection", koltoInjetionOn => HealTarget)
                     )),

                // Routine
                // AoE
                CastOnGround("Orbital Strike", orbitalStrikeOn => MyTarget.Position, orbitalStrikeWhen => (!Me.IsInParty() ? (Me.MobCountAround(Global.Distance.MeleeAoE) >= 4) : (MyTarget.MobCountAround(Global.Distance.MeleeAoE) >= 4))),
                Cast("Fragmentation Grenade", fragmentationGrenadeWhen => MyTarget.MobCountAround(Global.Distance.MeleeAoE) >= 3),
                Cast("Carbine Burst", carbineBurstWhen => Me.MobCountAround(Global.Distance.Melee) >= 3 && Me.HasMirrorBuffStacks("Tactical Advantage", 1)), // Blaster Volley

                // Single Target
                Cast("Corrosive Dart", corrosiveDartWhen => Global.RequiresCrowdControl && !MyTarget.HasMirrorDebuff("Poisoned (Tech)")), // Vital Shot ( Bleeding (Tech) )
                Cast("Shiv"), // Blaster Whip
                BuffSelf("Acid Blade", acidBladeWhen => Me.CanMirrorCast("Backstab", MyTarget)), // Flechette Round ( Back Blast )
                Cast("Backstab"), // Back Blast
                Cast("Laceration", lacerationWhen => Me.HasMirrorBuffStacks("Tactical Advantage")), // Sucker Punch ( Upper Hand )
                Cast("Rifle Shot"),// Flurry of Bolts

                //Movement
                CreateBTPS.MoveWithinRangeAndLoS(target => MyTarget, Global.Distance.Melee)
                );
        }


        [Behavior(BehaviorType.OutOfCombat)]
        [Class(CharacterClass.Agent, AdvancedClass.Operative, SkillTreeId.OperativeConcealment)]
        [Class(CharacterClass.Smuggler, AdvancedClass.Scoundrel, SkillTreeId.ScoundrelScrapper)]
        public static Composite OperativeConcealment_ScoundrelScrapper_OutOfCombat()
        {
            // NB: Apparently, BWcore will call this routine when in combat on occasion.  It is also called while we're pulling.
            return (new PrioritySelector(
                TargetSelect.CreateBTPS_UpdateForBattlefieldConditions(),
                new Decorator(oocBuffWhen => !Me.IsMounted,
                    new PrioritySelector(
                        // Only break cover when we're not in pull...
                        new Decorator(breakCoverWhen => !Me.InCombat && !TargetSelect.IsAtThePull(),
                            CreateBTPS.BreakCrouchOrCover())     // Prevents the 'stuck handler dance' if combat ends in crouch/cover
                        ))
                ));
        }
    }
}